#include "thread_pool.h"
#include "server_util.h"
//每一个具体任务的执行，交给一个成员来实现

void cdCommand(task_t *task) 
{
    WriteLog("execute cd command.\n");
    char *path = task->data;

    int result = chdir(path); // 改变工作目录
    if (result == -1) {
        perror("chdir");
    } else {
        WriteLog("Successfully changed directory to: %s\n", path);
    }
}

void lsCommand(task_t * task)
{
    WriteLog("execute ls command.");
    FILE *fp;
    char buff[2048];
    fp=popen("ls","r");
    if (fp == NULL) {
        perror("popen");
        WriteLog("lsCommand--execute ls command  error.");
        exit(EXIT_FAILURE);
    }
    int ret=fread(buff,1,sizeof(buff)-1,fp);
    buff[ret]='\0';
    strncpy(task->data,buff,sizeof(task->data) - 1);
     task->data[sizeof(task->data) - 1] = '\0'; // 确保以空字符结尾
    transferTaskData(task);
}

//Fmy 6.17
void pwdCommand(task_t *task) 
{
    WriteLog("execute pwd command.\n");
    fflush(stdout);

    char cwd[PATH_MAX];
    if (getcwd(cwd, sizeof(cwd)) != NULL) {
        strncpy(task->data, cwd, sizeof(task->data) - 1);
        task->data[sizeof(task->data) - 1] = '\0'; // 确保以空字符结尾
    } else {
        perror("getcwd() error");
        strncpy(task->data, 
                "error getting current working directory", 
                sizeof(task->data) - 1);
        task->data[sizeof(task->data) - 1] = '\0'; // 确保以空字符结尾
    }
    transferTaskData(task);
}

void rmdirCommand(task_t * task)
{
    char fullPath[4096];
    realpath(task->data, fullPath);  // 获取文件的绝对路径
    WriteLog("execute rm command.\n");
    if (remove(fullPath) == 0) {
        WriteLog("File '%s' deleted successfully.\n", fullPath);
    } else {
        fprintf(stderr, "Error deleting file '%s': %s\n", fullPath, strerror(errno));
    }
}

void mkdirCommand(task_t *task) 
{
    WriteLog("execute mkdir command.\n");
    if (task == NULL) {
        WriteLog("Error: task is NULL.\n");
        return;
    }
    // 从任务结构体中获取数据
    const char *dirname = task->data;

    if (mkdir(dirname, 0755) == 0) {
        WriteLog("Directory '%s' created successfully.\n", dirname);
    } else {
        perror("mkdir");
    }
}
//Fmy 6.17 END

void notCommand(task_t * task)
{
    WriteLog("execute not command.\n");
}

void putsCommand(task_t * task) {
    WriteLog("execute puts command.\n");
    char filename[100] = {0};
    int len = 0;
    int cmdType = 0;
    int ret = recv(task->peerfd, &len, sizeof(len), 0);//先接长度
    if(len == -1){
        return;
    }
    printf("ret: %d, filename's len:%d\n", ret, len);
    ret = recvn(task->peerfd, (char*)&cmdType, sizeof(cmdType));//再接类型
    ret = recvn(task->peerfd, filename, len);//再接内容
    printf("ret: %d, filename:%s\n", ret, filename);

    int wfd = open(filename, O_CREAT | O_RDWR, 0644);
    if(wfd == -1){
        perror("open");
        return;
    }
    //再获取的是文件长度
    off_t length = 0;
    recvn(task->peerfd, (char*)&length, sizeof(length));
    printf("file length: %ld\n", length);

    //最后接收文件内容
    //接收小文件
    //gzt-6.19
    if(length < 104857600){
        off_t splice = length / 100;
        off_t currSize = 0;
        off_t lastSize = 0;
        char buff[1000] = {0};
        off_t left = length;
        while(left > 0) {
            left = length - currSize;
            if(left >= 1000) {
                ret = recvn(task->peerfd, buff, sizeof(buff));//再接文件内容
            } else if(left < 1000 && left > 0){
                ret = recvn(task->peerfd, buff, left);
            } else {
                break;
            }
            //最后再写入本地
            ret = write(wfd, buff, ret);
            currSize += ret;
            if(currSize - lastSize > splice) {
                printf("has complete %5.2lf%%\r", (double)currSize / length * 100);
                fflush(stdout);
                lastSize = currSize;
            }
        }
        printf("has complete 100.00%%\n");
        close(wfd);
        return;
    }

    //接收大文件
    //假设磁盘空间不够了,如果继续写入，会报错
    //因此需要先确定是否有足够的空间来存放文件
    //此时需要先构建一个文件空洞
    ftruncate(wfd, length);
    char * pMap = (char*)mmap(NULL, length, PROT_READ|PROT_WRITE, MAP_SHARED, wfd, 0);
    if(pMap) {//映射成功
        //clientfd代表的是内核态套接字的缓冲区
        //pMap代表的是内核文件缓冲区
        int ret = recv(task->peerfd, pMap, length, MSG_WAITALL);
        printf("ret: %d\n", ret);
    }

    close(wfd);
    return;

}

void getsCommand(task_t * task) {
    WriteLog("execute gets command.\n");
    //获取文件名
    char* filename = task->data;
    //进行文件的发送
    //1. 先发送文件名
    train_t t;
    memset(&t, 0, sizeof(t));

    int fd = open(filename, O_RDWR);
    if(fd == -1){
        int len = -1;
        perror("open");
        send(task->peerfd, &len, 4, 0);
        return;
    }

    t.len = strlen(filename);
    strcpy(t.buff, filename);
    send(task->peerfd, &t, 8 + t.len, 0);

    memset(&t, 0, sizeof(t));

    //2.获取文件的长度
    struct stat fileInfo;
    memset(&fileInfo, 0, sizeof(fileInfo));
    fstat(fd, &fileInfo);
    off_t length = fileInfo.st_size;
    printf("file length: %ld\n", length);

    //发送文件的长度
    sendn(task->peerfd, &length, sizeof(length));

    //发送文件内容
    //发送小文件
    //gzt-6.19
    if(length < 104857600){
        char buff[1000] = {0};
        off_t currSize = 0;
        off_t lastSize = 0;
        off_t splice = length / 100;
        while(1){
            memset(&buff, 0, sizeof(buff));
            int ret = read(fd, buff, sizeof(buff));
            if(ret <= 0){
                break;
            }
            ret = sendn(task->peerfd, buff, strlen(buff));
            if(ret == -1){
                break;
            }
            currSize += ret;
            if(currSize - lastSize > splice){
                printf("has complete %5.2lf%%\r", (double)currSize / length * 100);
                fflush(stdout);
                lastSize = currSize;
            }
        }
        printf("has complete 100.00%%\n");
        printf("send file over.\n");
        close(fd);
        return;
    }

    //发送大文件
    char * pMap = (char*)mmap(NULL, fileInfo.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
    if(pMap) {
        //pMap代表的是内核中的文件缓冲区
        //sockfd代表的是套接字缓冲区
        int ret = send(task->peerfd, pMap, fileInfo.st_size, 0);
        printf("ret: %d, send file over.\n", ret);
    }

    close(fd);//关闭文件
    return;
}

